use std::sync::Arc;
use std::time::Duration;
use tokio::time;
use tracing::{info, Level};
use tracing_subscriber::FmtSubscriber;
use anyhow::Result;
use async_trait::async_trait;

use protoactor_rs::actor::{Actor, ActorContext, ActorError};
use protoactor_rs::cluster::{
    ClusterConfig, ClusterSystem, MemoryProvider,
    grain::{Grain, GrainContext, GrainClient, BaseGrain},
};
use protoactor_rs::remote::{Config as RemoteConfig, Remote};
use protoactor_rs::system::ActorSystem;

// 自定义虚拟Actor
struct HelloGrain {
    id: String,
    name: String,
    greetings_count: usize,
}

impl HelloGrain {
    fn new(id: &str) -> Self {
        Self {
            id: id.to_string(),
            name: "World".to_string(),
            greetings_count: 0,
        }
    }
}

// 消息类型
struct SetName {
    name: String,
}

struct SayHello;

struct GetStats;

#[async_trait::async_trait]
impl Actor for HelloGrain {
    type Context = GrainContext;
    
    async fn receive(&self, ctx: &mut Self::Context, msg: Box<dyn std::any::Any + Send>) -> Result<(), ActorError> {
        if let Some(set_name) = msg.downcast_ref::<SetName>() {
            let mut this = self.clone();
            this.name = set_name.name.clone();
            ctx.respond(format!("Name set to: {}", this.name));
        } else if let Some(_) = msg.downcast_ref::<SayHello>() {
            let mut this = self.clone();
            this.greetings_count += 1;
            ctx.respond(format!("Hello, {}!", this.name));
        } else if let Some(_) = msg.downcast_ref::<GetStats>() {
            ctx.respond(format!("Greeted {} times", self.greetings_count));
        }
        
        Ok(())
    }
}

impl Clone for HelloGrain {
    fn clone(&self) -> Self {
        Self {
            id: self.id.clone(),
            name: self.name.clone(),
            greetings_count: self.greetings_count,
        }
    }
}

#[async_trait::async_trait]
impl Grain for HelloGrain {
    fn id(&self) -> &str {
        &self.id
    }
    
    fn kind(&self) -> &str {
        "hello"
    }
    
    async fn activate(&mut self) -> Result<()> {
        info!("HelloGrain activated: {}", self.id);
        Ok(())
    }
    
    async fn deactivate(&mut self) -> Result<()> {
        info!("HelloGrain deactivated: {}", self.id);
        Ok(())
    }
}

#[tokio::main]
async fn main() -> Result<()> {
    // 设置日志
    let subscriber = FmtSubscriber::builder()
        .with_max_level(Level::INFO)
        .finish();
    tracing::subscriber::set_global_default(subscriber).expect("setting default subscriber failed");
    
    // 创建Actor系统
    let system = ActorSystem::new();
    
    // 配置远程通信
    let remote_config = RemoteConfig::new()
        .with_host("127.0.0.1:8090")
        .build();
    
    // 创建远程模块
    let remote = Arc::new(Remote::new(system.clone(), remote_config));
    remote.start().await?;
    
    // 创建一个基于内存的集群提供者
    let memory_provider = Arc::new(MemoryProvider::new());
    
    // 配置集群
    let cluster_config = ClusterConfig {
        name: "test-cluster".to_string(),
        host: "127.0.0.1".to_string(),
        port: 8090,
        heartbeat_interval: 1,
        unreachable_timeout: 5,
        down_timeout: 10,
    };
    
    // 创建集群系统
    let (mut cluster_system, mut event_rx) = ClusterSystem::new(
        memory_provider,
        cluster_config,
        remote,
    );
    
    // 启动集群
    cluster_system.start().await?;
    
    info!("Cluster system started");
    
    // 处理集群事件
    tokio::spawn(async move {
        while let Some(event) = event_rx.recv().await {
            info!("Received cluster event: {:?}", event);
        }
    });
    
    // 等待集群初始化
    time::sleep(Duration::from_secs(1)).await;
    
    // 创建Grain客户端
    let cluster_ref = Arc::new(cluster_system);
    let mut client = GrainClient::new(cluster_ref.clone(), "hello", "grain1");
    
    // 调用Grain方法
    client.send(SetName { name: "Proto.Actor".to_string() }).await?;
    time::sleep(Duration::from_millis(100)).await;
    
    let greeting: String = client.request::<String>(SayHello, Duration::from_secs(5)).await?;
    info!("Got greeting: {}", greeting);
    
    let stats: String = client.request::<String>(GetStats, Duration::from_secs(5)).await?;
    info!("Stats: {}", stats);
    
    // 等待一段时间后关闭
    time::sleep(Duration::from_secs(2)).await;
    
    Ok(())
} 